package com.ls.fw.web.file.support.down;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.ls.fw.commons.core.utils.Encodes;
import com.ls.fw.commons.core.utils.file.FileUtil;
import com.ls.fw.web.core.http.bean.ContentType;
import com.ls.fw.web.core.servlet.bean.AjaxResult;
import com.ls.fw.web.core.servlet.bean.ValidResult;
import com.ls.fw.web.file.bean.DownStyle;
import com.ls.fw.web.file.servlet.BaseFileServlet;
import com.ls.fw.web.file.support.http.FileDownloader;
import com.ls.fw.web.file.support.http.FileDownloader.Result;

/**
 * 下载文件基类
 * 参数:
 *  savename:保存名称
 *  type:下载方式：0,1,2,3
 *  open:是否直接打开：0,1
 * @author Defender
 * 2014年2月22日 下午5:07:51
 */
public abstract class BaseDown extends BaseFileServlet {
	
	/**
	 * 
	 */
	private static final long serialVersionUID = -1611105069637189255L;

	/** 默认字节交换缓冲区大小 */
	public static final int DEFAULT_BUFFER_SIZE			= 1024 * 4;
	
	/** 下载文件的默认 Mime Type */
	public static final String DEFAULT_CONTENT_TYPE		= "application/force-download;";
	
	public static final String DEFAULT_AGENT_CHARSET	= "UTF8";
	
	@Override
	public void init() throws ServletException {
		super.init();
		//私定
		String _baseDir = this.getInitParameter(BaseDown.BASEDIR);
		if(!this.isEmpty(_baseDir)){
			this.relativeDirPara = _baseDir;
		}
		String _isAbsolutePath = this.getInitParameter(BaseDown.ISABSOLUTEPATH);
		this.handlPara(_baseDir,_isAbsolutePath);
	}
	
	
	@Override
	protected void illegalRequest(ValidResult validResult,
			HttpServletRequest request, HttpServletResponse response,
			Object... paras) {
		Map<String,Object> map = new HashMap<String,Object>(2);
		map.put(STATUS_CODE, AjaxResult.FAIL);
		if(paras==null){
			map.put(MSG, validResult.getDesc());
		}else{
			map.put(MSG, paras);
		}
		map.put(RESULT, "");
		this.sendJSONObject(response,map);
		
	}
	@Override
	protected void exceptionCaught(HttpServletRequest request,
			HttpServletResponse response, Object result, Throwable throwable) {
		this.log(result.toString(), throwable);
		Map<String,Object> map = new HashMap<String,Object>(2);
		map.put(STATUS_CODE, AjaxResult.FAIL);
		map.put(RESULT, result);
		map.put(MSG, throwable.getMessage());
		this.sendJSONObject(response,map);
	}
	
	protected void callback(HttpServletRequest request,
			HttpServletResponse response, String path, String saveName){
		this.log("执行callback，下载成功："+path+",保存名称："+saveName);
	}
	
	@Override
	protected void handlRequest(SubmitType submitType,
			HttpServletRequest request, HttpServletResponse response) {
		String type_str = this.getParameter(request,"type");
		int type = 0;
		if(type_str!=null && !"".equals(type_str)){
			try{
				type = Integer.parseInt(type_str);
			}catch(Exception e){
				this.log(e.getMessage(), e);
			}
		}
		String path = this.checkSeparator(this.getPath(request));
		path = Encodes.urlDecode(path);
		String saveName = this.getSaveName(request,path);
		// 判断文件是否存在
		if(!this.theDownFileIsExist(path)){
 			// 记录日志
			this.exceptionCaught(request,response,"文件不存在！",new Exception("文件["+path+"]不存在！"));
			return;
		}
		// 检查下载结果
	    Result result = null;
		try {
			result = this.down(request,response,DownStyle.value(type),path,saveName,this.isOpen(request));
		} catch (IOException e) {
			this.exceptionCaught(request,response,"下载失败",e);
			return;
		}
		if(result==null || result != Result.SUCCESS){
			this.exceptionCaught(request,response,"下载失败",new Exception("下载失败"));
			return;
		}
		this.callback(request, response, path, saveName);
	}
	
	
	
	/**
	 * 该下载文件是否存在
	 * @author Defender
	 * 2013-8-3 下午06:36:47
	 * @param path
	 * @return
	 */
	private boolean theDownFileIsExist(String path){
		File file = new File(path);
		boolean flag = file.exists();
        return flag;
	}
	
	protected String getSaveName(HttpServletRequest request) {
		return (String) this.getParameter(request,SAVENAME);
	}
	/**
	 * 文件保存名称
	 * @author Defender
	 * 2014年2月22日 下午5:49:56
	 * @return
	 */
	protected String getSaveName(HttpServletRequest request,String path) {
		 String fileName = "error.txt";
		 fileName = this.getSaveName(request);
		 if(this.isEmpty(fileName)){
			 fileName = "error.txt";
			 File file = new File(path);
			 if(file.exists()){
				 fileName = file.getName();
			 }
		 }
		fileName = Encodes.urlDecode(fileName);
		return fileName;
	}
	
	
	/**
	 * 需要下载的文件所在路径
	 * @author Defender
	 * 2014年2月22日 下午5:49:45
	 * @return
	 */
	protected abstract String getPath(HttpServletRequest request);
	
	
	/**
	 * 需要下载的流
	 * @author Defender 
	 * 2014年6月8日上午1:06:53
	 * @param request
	 * @return
	 */
	protected abstract InputStream getInputStream(HttpServletRequest request);
	
	/**
	 * 是否直接打开文件
	 * @author Defender
	 * 2014年2月23日 下午12:07:57
	 * @param request
	 * @return
	 */
	protected  boolean isOpen(HttpServletRequest request){
		boolean falg = false;
		String open = this.getParameter(request, "open");
		if(open!=null && !"".equals(open)){
			if("true".equalsIgnoreCase(open.toLowerCase())){
				falg = true;
			}else if("1".equals(open)){
				falg = true;
			}
		}
		return falg;
	}
	
	/**
	 * 下载文件
	 * @author Defender
	 * 2013-8-3 下午05:04:31
	 * @param type 下载方式
	 * @param path 文件路径
	 * @param saveName 保存名称
	 * @return
	 * @throws IOException
	 */
	public Result down(HttpServletRequest request, HttpServletResponse response,DownStyle style
			,String path,String saveName,boolean isOpen) throws IOException{
		
		this.log("使用type="+style+",开始下载："+path);
		DownStyle m_style = style;
		if(m_style==null){
			m_style = DownStyle.STREAM;
		}
		FileDownloader fdl	= null;
		InputStream fis		= null;
		File ff = new File(path);
		boolean exist = false;
		if(ff.exists()){
			exist = true;
			fis = new FileInputStream(ff);
		}else{
			fis = this.getInputStream(request);
		}
		switch(m_style){
			case ABSOLUTE:// 物理文件（绝对路径）
				 // 创建 FileDownloader 对象
				 fdl	= new FileDownloader(path);
				 // 根据需要调用 setters 设置下载属性
				 fdl.setSaveFileName(saveName);
				break;
			case BYTEARRAY:// 字节数组
				byte[] bytes		= null;
				bytes = new byte[fis.available()];
				fis.read(bytes);
				if(fis!=null){
					fis.close();
				}
	     		// 创建 FileDownloader 对象
				fdl = new FileDownloader(bytes, saveName);
				break;
			case BYTESTREAM:// 字节流
				// 创建 FileDownloader 对象
				fdl = new FileDownloader(fis, saveName);
				break;
			case STREAM:
			default:
				// 创建 FileDownloader 对象
			 	fdl = new FileDownloader(fis, saveName);
				break;
		}
		if(exist){
			String ext = FileUtil.getFileSuffixName(path);
			ContentType t = ContentType.value(ext);
			if(t==null){
				t = ContentType.stream;
			}
			fdl.setContentType(t.getType());
		}
		
		// 执行下载
		 FileDownloader.Result result = fdl.download(request, response,isOpen);
		return result;
	}

	public Result down(HttpServletRequest request, HttpServletResponse response,DownStyle style
			,InputStream is,String saveName,boolean isOpen) throws IOException{
		this.log("使用type="+style+"开始下载！");
		FileDownloader fdl	= null;
		fdl = new FileDownloader(is, saveName);
		// 执行下载
		 FileDownloader.Result result = fdl.download(request, response,isOpen);
		return result;
	}
	
	@Override
	protected boolean isLegalRequest(HttpServletRequest request) {
		return false;
	}

	 
}
